﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Microsoft.SharePoint;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using SP = Microsoft.SharePoint.Client;

namespace com.sharepointutils.application
{
    public partial class MainForm : Form
    {
        public MainForm(String associatedFile)
        {
            InitializeComponent();

            if (!String.IsNullOrEmpty(associatedFile))
            {
                OpenQueryWindow(associatedFile);
            }
        }

        public void ReportError(Exception ex)
        {
            errorList_main.AddError(ex);
        }

        public TreeNode SelectedNode { get { return treeView_main.SelectedNode; } }

        #region Form Functions

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            AboutBox about = new AboutBox();
            about.Show();
        }

        SiteInformation copyConnection = null;
        String copyList = "";

        private void copyToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            copyConnection = treeView_main.SelectedNode.Parent.Tag as SiteInformation;
            copyList = treeView_main.SelectedNode.Text;
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (copyConnection != null)
                {
                    SiteInformation pasteConnection = treeView_main.SelectedNode.Parent.Tag as SiteInformation;
                    if (MessageBox.Show("Are you sure you want to copy " + copyList + " to " + pasteConnection.URL + "?", "Paste?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                    {
                        SharePointUtilities.copyList(copyConnection.URL, copyConnection.Credentials, pasteConnection.URL, pasteConnection.Credentials, copyList);
                    }
                }
            }
            catch (Exception ex)
            {
                ReportError(ex);
            }
        }

        private void pasteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                if (copyConnection != null)
                {
                    SiteInformation pasteConnection = treeView_main.SelectedNode.Tag as SiteInformation;
                    if (MessageBox.Show("Are you sure you want to copy " + copyList + " to " + pasteConnection.URL + "?", "Paste?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                    {
                        SharePointUtilities.copyList(copyConnection.URL, copyConnection.Credentials, pasteConnection.URL, pasteConnection.Credentials, copyList);
                    }
                }
            }
            catch (Exception ex)
            {
                ReportError(ex);
            }
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            treeView_main.SelectedNode.Nodes.Clear();
            SiteInformation refreshConnection = treeView_main.SelectedNode.Tag as SiteInformation;
            treeView_main.SelectedNode.Nodes.Add(loadLists(refreshConnection));
            treeView_main.SelectedNode.Nodes.Add(loadSubsites(refreshConnection));
            treeView_main.SelectedNode.Nodes.Add(loadSiteColumns(refreshConnection));
            treeView_main.SelectedNode.Nodes.Add(loadSiteContentTypes(refreshConnection));
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (MessageBox.Show("Are you sure you want to delete " + treeView_main.SelectedNode.Text + "?", "Delete?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    SiteInformation connection = treeView_main.SelectedNode.Parent.Tag as SiteInformation;
                    SharePointUtilities.deleteList(connection.URL, connection.Credentials, treeView_main.SelectedNode.Text);
                }
            }
            catch (Exception ex)
            {
                ReportError(ex);
            }
        }

        private void treeView_main_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                treeView_main.SelectedNode = e.Node;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        System.Net.NetworkCredential credentials = null;
        TaskFactory OpenTaskFactory = new TaskFactory();

        private void OpenSite()
        {
            try
            {
                OpenSiteForm siteForm = new OpenSiteForm();
                if (siteForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    if (!String.IsNullOrEmpty(siteForm.Username))
                    {
                        credentials = new System.Net.NetworkCredential(siteForm.Username, siteForm.Password, siteForm.Domain);
                    }
                    lbl_status.Text = "Loading Site...";
                    progbar_status.Value = 0;

                    OpenTaskFactory.StartNew(() => loadSite(siteForm.Site, credentials));
                }
            }
            catch (Exception ex)
            {
                ReportError(ex);
            }

        }

        private TreeNode loadSubsites(SiteInformation connection)
        {
            TreeNode sitesNode = new TreeNode("Sub-sites");
            try
            {
                foreach (SiteInformation sc in SharePointUtilities.getSubsites(connection.URL, connection.Credentials))
                {
                    TreeNode listNode = new TreeNode(sc.SiteName);
                    listNode.Tag = sc;
                    listNode.ImageIndex = 0;
                    listNode.SelectedImageIndex = 0;
                    listNode.ContextMenuStrip = contextMenuStrip_site;
                    sitesNode.Nodes.Add(listNode);
                }

            }
            catch (Exception ex)
            {
                exceptionQueue.Enqueue(ex);
            }
            return sitesNode;
        }

        private TreeNode loadSiteColumns(SiteInformation connection)
        {
            TreeNode fieldsNode = new TreeNode("Site Columns");
            try
            {
                foreach (Microsoft.SharePoint.Client.Field field in SharePointUtilities.GetSiteColumns(connection.URL, connection.Credentials).OrderBy(f => f.Title))
                {
                    TreeNode fieldNode = new TreeNode(field.Title);
                    fieldNode.Tag = field;
                    fieldNode.ImageIndex = 4;
                    fieldNode.SelectedImageIndex = 4;
                    fieldNode.ContextMenuStrip = contextMenuStrip_Column;
                    fieldsNode.Nodes.Add(fieldNode);
                }
            }
            catch (Exception ex)
            {
                exceptionQueue.Enqueue(ex);
                //ErrorLog.Append(Environment.NewLine + "Error loading lists: " + ex.Message);
            }

            return fieldsNode;
        }

        private TreeNode loadSiteContentTypes(SiteInformation connection)
        {
            TreeNode fieldsNode = new TreeNode("Site Content Types");
            try
            {
                foreach (Microsoft.SharePoint.Client.ContentType contentType in SharePointUtilities.GetSiteContentTypes(connection.URL, connection.Credentials).OrderBy(c => c.Name))
                {
                    TreeNode node = new TreeNode(contentType.Name);
                    node.Tag = contentType;
                    node.ImageIndex = 5;
                    node.SelectedImageIndex = 5;
                    fieldsNode.Nodes.Add(node);
                }
            }
            catch (Exception ex)
            {
                exceptionQueue.Enqueue(ex);
                //ErrorLog.Append(Environment.NewLine + "Error loading lists: " + ex.Message);
            }

            return fieldsNode;
        }

        private TreeNode loadLists(SiteInformation connection)
        {
            TreeNode listsNode = new TreeNode("Lists and Libraries");
            try
            {
                foreach (Microsoft.SharePoint.Client.List li in SharePointUtilities.getListsWithListInformation(connection.URL, connection.Credentials))
                {
                    TreeNode listNode = new TreeNode(li.Title);
                    listNode.Tag = li;
                    listNode.ContextMenuStrip = contextMenuStrip_list;
                    Boolean isDocumentLibrary = (li.BaseType.ToString() == "DocumentLibrary");
                    listNode.ImageIndex = isDocumentLibrary ? 2 : 1;
                    listNode.SelectedImageIndex = isDocumentLibrary ? 2 : 1;

                    TreeNode viewListNode = new TreeNode("Views");
                    viewListNode.ImageIndex = 3;
                    viewListNode.SelectedImageIndex = 3;

                    TreeNode fieldListNode = new TreeNode("Fields");
                    fieldListNode.ImageIndex = 4;
                    fieldListNode.SelectedImageIndex = 4;

                    TreeNode contentTypeListNode = new TreeNode("Content Types");
                    contentTypeListNode.ImageIndex = 5;
                    contentTypeListNode.SelectedImageIndex = 5;

                    List<Microsoft.SharePoint.Client.View> views = li.Views.ToList();
                    foreach (Microsoft.SharePoint.Client.View v in views.OrderBy(vi => vi.Title))
                    {
                        TreeNode viewNode = new TreeNode(v.Title);
                        viewNode.Tag = v;
                        viewNode.ImageIndex = 3;
                        viewNode.SelectedImageIndex = 3;
                        viewListNode.Nodes.Add(viewNode);
                    }
                    listNode.Nodes.Add(viewListNode);

                    List<Microsoft.SharePoint.Client.Field> fields = li.Fields.ToList();
                    foreach (Microsoft.SharePoint.Client.Field f in fields.OrderBy(f => f.Title))
                    {
                        TreeNode fieldNode = new TreeNode(f.Title);
                        fieldNode.Tag = f;
                        fieldNode.ImageIndex = 4;
                        fieldNode.SelectedImageIndex = 4;
                        fieldListNode.Nodes.Add(fieldNode);
                    }
                    listNode.Nodes.Add(fieldListNode);


                    List<Microsoft.SharePoint.Client.ContentType> contentTypes = li.ContentTypes.ToList();
                    foreach (Microsoft.SharePoint.Client.ContentType c in contentTypes.OrderBy(c => c.Name))
                    {
                        TreeNode contentTypeNode = new TreeNode(c.Name);
                        contentTypeNode.Tag = c;
                        contentTypeNode.ImageIndex = 5;
                        contentTypeNode.SelectedImageIndex = 5;
                        contentTypeListNode.Nodes.Add(contentTypeNode);
                    }
                    listNode.Nodes.Add(contentTypeListNode);

                    listsNode.Nodes.Add(listNode);
                }
            }
            catch (Exception ex)
            {
                exceptionQueue.Enqueue(ex);
                //ErrorLog.Append(Environment.NewLine + "Error loading lists: " + ex.Message);
            }
            
            return listsNode;
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenSite();
        }

        private void btn_connect_Click(object sender, EventArgs e)
        {
            OpenSite();
        }

        private void btn_disconnect_Click(object sender, EventArgs e)
        {
            disconnectSite();
        }

        private void disconnectSite()
        {
            if (treeView_main.SelectedNode != null)
            {
                treeView_main.SelectedNode.Remove();
            }
        }

        private void btn_refresh_Click(object sender, EventArgs e)
        {

        }

        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            disconnectSite();
        }

        private void disconnectToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            disconnectSite();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SiteInformation temp = treeView_main.SelectedNode.Tag as SiteInformation;
            System.Diagnostics.Process.Start(temp.URL);
        }

        private void treeView_main_AfterSelect(object sender, TreeViewEventArgs e)
        {
            changedProperties = new Dictionary<string, object>();
            propertyGrid.SelectedObject = e.Node.Tag;
        }


        Queue<Exception> exceptionQueue = new Queue<Exception>();

        private void loadSite(String url, System.Net.NetworkCredential cred)
        {
            TreeNode loadSite = null;
            try
            {
                SiteInformation SiteInformation = SharePointUtilities.getSiteInformation(url, cred);
                if (SiteInformation != null)
                {
                    loadSite = new TreeNode(SiteInformation.SiteName);
                    loadSite.Tag = SiteInformation;
                    loadSite.ContextMenuStrip = contextMenuStrip_site;
                    loadSite.ImageIndex = 0;
                    loadSite.SelectedImageIndex = 0;
                    loadSite.Nodes.Add(loadLists(SiteInformation));
                    loadSite.Nodes.Add(loadSubsites(SiteInformation));
                    loadSite.Nodes.Add(loadSiteColumns(SiteInformation));
                    loadSite.Nodes.Add(loadSiteContentTypes(SiteInformation));
                    this.Invoke((MethodInvoker)delegate { loadSiteComplete(loadSite); });
                }
                else
                {
                    throw(new Exception("Site not found!"));
                }
            }
            catch (Exception ex)
            {
                exceptionQueue.Enqueue(ex);
            }
            finally
            {
                this.Invoke((MethodInvoker)delegate { displayExceptionsinQueue(); });
            }
        }

        private void displayExceptionsinQueue()
        {
            while (exceptionQueue.Count > 0)
            {
                ReportError(exceptionQueue.Dequeue());
            }
            lbl_status.Text = "Done...";
            progbar_status.Value = 100;
        }

        private void loadSiteComplete(TreeNode node)
        {
            if (node != null)
            {
                treeView_main.Nodes.Add(node);
            }
            lbl_status.Text = "Done...";
            progbar_status.Value = 100;
        }

        private void txt_errorLog_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start(e.LinkText);
        }

        #endregion

        #region Bottom Tab Control

        private void btn_clear_Click(object sender, EventArgs e)
        {
            errorList_main.ClearLog();
        }
        #endregion

        #region Panel View Functions

        private void btn_close_sites_Click(object sender, EventArgs e)
        {
            panel_left.Visible = false;
        }

        private void btn_close_properties_Click(object sender, EventArgs e)
        {
            panel_right.Visible = false;
        }

        private void propertiesWindowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            panel_right.Visible = true;
        }

        private void connectionWindowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            panel_left.Visible = true;
        }

        private void btn_close_output_Click(object sender, EventArgs e)
        {
            panel_bottom.Visible = false;
        }

        private void ToolStripMenuItem_output_Click(object sender, EventArgs e)
        {
            panel_bottom.Visible = true;
        }

        #endregion

        #region Tool Strip Buttons

        private void toolStripButton_upload_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();

                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.UploadForm form = new Forms.UploadForm(conn, this);
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }


        private void tsb_sites_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();
                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                //Forms.SitesForm form = new Forms.SitesForm(conn);
                //form.MdiParent = this;
                //form.Show();
                //form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void toolStripButton_download_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();
                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.DownloadForm form = new Forms.DownloadForm(conn);
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void toolStripButton_query_Click(object sender, EventArgs e)
        {
            OpenQueryWindow();
        }

        private void OpenQueryWindow()
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();
                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.QueryForm form = new Forms.QueryForm(conn);
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void OpenQueryWindow(String associatedFile)
        {
            try
            {
                Forms.QueryForm form = new Forms.QueryForm(associatedFile);
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }
        
        private void toolStripButton_modifyListItems_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();
                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.ListItemModifyForm form = new Forms.ListItemModifyForm(conn, this);
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void toolStripButton_wiki_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();
                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.WikiForm form = new Forms.WikiForm(conn);
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void toolStripButton_security_Click(object sender, EventArgs e)
        {
            try
            {
                SharePointConnection conn = new SharePointConnection();

                FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                Forms.SecurityForm form = new Forms.SecurityForm(conn);
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        private void toolStripButton_open_Click(object sender, EventArgs e)
        {
            OpenSite();
        }

        private void toolStripButton_disconnect_Click(object sender, EventArgs e)
        {
            disconnectSite();
        }

        private void toolStripButton_httpRequestBuilder_Click(object sender, EventArgs e)
        {
            try
            {
                Forms.HttpRequestBuilderForm form = new Forms.HttpRequestBuilderForm();
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }


        private void toolStripButton_copy_Click(object sender, EventArgs e)
        {
            try
            {
                Forms.UpdateForm form = new Forms.UpdateForm();
                form.MdiParent = this;
                form.Show();
                form.WindowState = FormWindowState.Maximized;
            }
            catch (Exception ex)
            {
                ReportError(ex);
                //ErrorLog.Append("Error loading Form! " + ex.Message);
            }
        }

        #endregion

        #region Properties Panel
        Dictionary<String, object> changedProperties = new Dictionary<string, object>();

        private void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            changedProperties[e.ChangedItem.Label] = e.ChangedItem.Value;
        }

        private void btn_properties_add_Click(object sender, EventArgs e)
        {
            SharePointConnection conn = new SharePointConnection();
            FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
            Forms.AddForm form = new Forms.AddForm(conn);
            if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

            }
        }

        private void button_updateProperties_Click(object sender, EventArgs e)
        {
            SharePointConnection conn = new SharePointConnection();
            FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);

            switch (treeView_main.SelectedNode.Tag.GetType().Name)
             {
                 case "View":
                     SP.View view = treeView_main.SelectedNode.Tag as SP.View;
                     SharePointUtilities.updateView(conn.URL, conn.Credentials, conn.List, view.Id, changedProperties);
                     break;
                case "Field":
                     SP.Field field = treeView_main.SelectedNode.Tag as SP.Field;
                     SharePointUtilities.UpdateField(conn.URL, conn.Credentials, conn.List, field, changedProperties);
                     break;
                case "ContentType":
                     SP.ContentType contentType = treeView_main.SelectedNode.Tag as SP.ContentType;
                    if (contentType.Scope.Contains("List"))
                    {
                        SharePointUtilities.UpdateContentType(conn.URL, conn.Credentials, conn.List, contentType, changedProperties);
                    }

                     break;
             }
        }

        private void errorList_main_ItemActivate(object sender, EventArgs e)
        {
            ExceptionForm form = new ExceptionForm(((ErrorList)sender).SelectedItems[0].Tag);
            form.Show();
        }

        private void btn_properties_delete_Click(object sender, EventArgs e)
        {
            try
            {
                if (MessageBox.Show("Are you sure you want to delete this field?", "Delete Field?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    SP.Field field = propertyGrid.SelectedObject as SP.Field;
                    if (field != null)
                    {
                        SharePointConnection conn = new SharePointConnection();
                        FormUtilities.OpenListNode(treeView_main.SelectedNode, conn);
                        SharePointUtilities.DeleteField(conn.URL, conn.Credentials, conn.List, field);
                    }
                    MessageBox.Show("Field Deleted Successfully!");
                }
            }
            catch (Exception ex)
            {
                ReportError(ex);
            }
        }
        
        #endregion

        private void treeView_main_ItemDrag(object sender, ItemDragEventArgs e)
        {
            TreeNode node = e.Item as TreeNode;
            if (node.Tag != null)
            {
                DoDragDrop((dynamic)node.Tag);
            }
        }

        private void DoDragDrop(object obj)
        {
            
        }

        private void DoDragDrop(SP.Field field)
        {
            if (field != null)
            {
                String data = String.Format("<FieldRef Name=\"{0}\" />",field.InternalName);
                treeView_main.DoDragDrop(data, DragDropEffects.Move);
            }
        }

        private void DoDragDrop(SP.View view)
        {
            if (view != null)
            {
                String data = "<View>" + view.ViewQuery + "</View>";
                treeView_main.DoDragDrop(data, DragDropEffects.Move);
            }
        }

        private void btn_viewXml_Click(object sender, EventArgs e)
        {
            if(propertyGrid.SelectedGridItem.Label == "SchemaXml")
            {
                try
                {
                    Forms.XMLViewerForm form = new Forms.XMLViewerForm(propertyGrid.SelectedGridItem.Value.ToString());
                    form.MdiParent = this;
                    form.Show();
                    form.WindowState = FormWindowState.Maximized;
                }
                catch (Exception ex)
                {
                    ReportError(ex);
                    //ErrorLog.Append("Error loading Form! " + ex.Message);
                }
            }


        }


    }

}
